<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/1/5 0005
 * Time: 上午 10:05
 */

namespace common\components\ActionsComponents;


use common\components\DataHelper;
use common\components\LanguageTemplate;
use common\components\OSS\AliOSS;
use OSS\Core\OssException;
use yii\helpers\ArrayHelper;

class UploadOssAction extends CommonAction
{
    public $isBase64 = false;

    public $isUrlDecode = true;

    public $bucket;

    public $filename;

    public $dir;

    public $uploadName;

    public $suffix;

    public $allowType = ['image/jpeg', 'image/png'];

    public $isRequest = true;

    //MB
    public $size = 2;

    public $isEditor = false;

    public static function getSuffixByMimeType($mimeType, $default = false)
    {
        $ret = [
            "image/jpeg" => 'jpg',
            "image/png" => 'png',
            "audio/mp3" => "mp3",
            "audio/wav" => "wav",
            "audio/mp4" => "mp4",
        ];

        return ArrayHelper::getValue($ret, $mimeType, $default);
    }

    public function run()
    {
        $controller = $this->controller;
        if ( $this->before instanceof \Closure ) {
            $before = $this->before;
            $ret = $before();
            if ( $ret !== true && !@$ret["status"] ) {
                return $controller->jsonResponse(
                    $controller::RESPONSE_FAILURE,
                    $ret["message"]
                );
            }
        }

        $aliOss = new AliOSS();
        $ossClient = $aliOss->initOssClient();

        !$this->bucket && $this->bucket = $aliOss->getConfig('bucket');
        !$this->filename && $this->filename = str_replace('.', '', uniqid(null, true));

        //这里是单独的文件名 不带路径
        $filename = $this->filename;
        if ( $this->dir ) {
            $this->filename = rtrim($this->dir, '/') . '/' . trim($this->filename, '/');
        }

        if ( $this->isBase64 ) {
            $object = \Yii::$app->request->getBodyParam($this->uploadName);
            //这里需要注意 上传的base64图片 必须urlencode编码

            $this->isUrlDecode && $object = urldecode($object);
            $object = str_replace([
                "data:image/png;base64,",
                "data:image/jpeg;base64,",
                " "
            ], "", $object);
            $object = base64_decode($object);#file_put_contents("D:/tmp.png", $object);var_dump($object);die;

            $fileSize = strlen($object);
            $size = $this->size * 1024 * 1024;
            if ( $fileSize > $size ) {
                return $this->isEditor ? $controller->asJson([
                    'state' => "上传文件最大为" . $this->size . "MB"
                ]) : $controller->jsonResponse(
                    $controller::RESPONSE_FAILURE,
                    "上传文件最大为" . $this->size . "MB"
                );
            }

            //这里来校验一下指定的类型
            $fileInfo = finfo_open();
            $mime_type = finfo_buffer($fileInfo, $object, FILEINFO_MIME_TYPE);

            if ( $this->allowType && !in_array($mime_type, $this->allowType) ) {
                return $this->isEditor ? $controller->asJson([
                    'state' => "错误的文件类型，只能上传" . implode(",", $this->allowType) . "类型文件"
                ]) : $controller->jsonResponse(
                    $controller::RESPONSE_FAILURE,
                    "错误的文件类型，只能上传" . implode(",", $this->allowType) . "类型文件"
                );
            }

            if ( !$this->suffix ) {
                $this->suffix = self::getSuffixByMimeType($mime_type);
                if ( !$this->suffix ) {
                    die;
                }
            }

            try {
                $uploadRet = $ossClient->putObject($this->bucket, $this->filename . '.' . $this->suffix, $object);#die(print_r($uploadRet));
            } catch ( OssException $e ) {
                return $this->isEditor ? $controller->asJson([
                    'state' => $e->getMessage()
                ]) : $controller->jsonResponse(
                    $controller::RESPONSE_FAILURE,
                    $e->getMessage()
                );
            }
        } else {
            $uploadRet = DataHelper::uploadFile($this->uploadName, $this->dir, false, $this->allowType, $this->size, $filename);
            if ( !$uploadRet['status'] ) return $this->isEditor ? $controller->asJson([
                'state' => $uploadRet['msg']
            ]) : $controller->jsonResponse(
                $controller::RESPONSE_FAILURE,
                $uploadRet['msg']
            );
            $uploadRet['oss-request-url'] = $uploadRet['url'];
        }

        if ( $this->isEditor ) {
            return  $controller->asJson([
                'state'=>'SUCCESS',
                'url'=>$uploadRet['oss-request-url'],//这里 如果是editor上传则直接添加水印保存
                'title'=>"",
                'original'=>$uploadRet['oss-request-url'],
                'type'=>"",
                'size'=>""
            ]);
        }

        $responseData = [
            'url' => $uploadRet['oss-request-url'],
        ];
        $thumb = DataHelper::qVal('thumb','%b',false, $this->_request);
        if ( $thumb ) {
            $w = DataHelper::qVal('w','%d{30,1000}',300, $this->_request);
            $h = DataHelper::qVal('h','%d{30,1000}',200, $this->_request);
            $responseData['thumb'] = AliOSS::imageResize($uploadRet['oss-request-url'], $w, $h);
        }

        if ( $this->callback instanceof \Closure ) {
            $callback = $this->callback;
            $callbackRet = $callback($responseData);
            if ( !$callbackRet ) {
                return  $controller->jsonResponse(
                    $controller::RESPONSE_FAILURE,
                    "上传失败"
                );
            }

            if ( is_array($callbackRet) ) {
                $responseData = array_merge($responseData, $callbackRet);
            }
        }

        return  $controller->jsonResponse(
            $controller::RESPONSE_SUCCESS,
            LanguageTemplate::tCommon(LanguageTemplate::RESPONSE_SUCCESS),
            $responseData
        );
    }

    /**
     * upload上传错误码映射
     * @param $key
     * @return mixed|string
     */
    public static function getUploadErrorMap($key)
    {
        $arrError = [
            UPLOAD_ERR_INI_SIZE=>'传文件大小超过服务器允许上传的最大值',
            UPLOAD_ERR_FORM_SIZE=>'上传文件大小超过HTML表单中隐藏域MAX_FILE_SIZE选项指定的值',
            UPLOAD_ERR_CANT_WRITE=>'文件写入失败',
            UPLOAD_ERR_EXTENSION=>'系统配置异常',
            UPLOAD_ERR_PARTIAL=>'文件上传不完整'
        ];

        if ( isset($arrError[$key]) ) return $arrError[$key];

        return '文件上传失败';
    }
}